const request = require('./utils/request')
const { getOpenid, loginByOpenid } = require('./utils/miniapp')
const financeAccount = require('./utils/finance-account')
const io = require('./utils/weapp.socket.io.js')
const { getCurrentConfig } = require('./config.js')
App({
  globalData: {
    isSocketConnect: false,
    userId: '',
    userInfo: null,
    /**
     * 尝试连接错误次数
     */
    tryConnectErrorCount: 1,
    // 添加环境配置到全局数据
    ...getCurrentConfig(),
    // 账户全局相关
    globaAccountList: [],
    globaAccountIndex: -1,
    // 公众号openid,用于第一次登录后绑定公众号用户没有登录，跳转到登录页面后，登录再进来，无法触发绑定的问题
    globalMpOpenid: '',
  },
  // 账户数据就绪回调列表
  accountReadyCallbacks: [],
  onLaunch() {
    // 展示本地存储能力
    // const logs = wx.getStorageSync('logs') || []
    // logs.unshift(Date.now())
    // wx.setStorageSync('logs', logs)

    // wx.removeStorageSync('openid')
    // 登录
    this.silentLogin();
  },
  // 登录中的状态与承诺，用于去重并发登录
  loginInProgress: false,
  loginPromise: null,
  /**
   * 静默登录
   */
  silentLogin(){
    if (this.loginInProgress && this.loginPromise) {
      return this.loginPromise;
    }
    this.loginInProgress = true;
    const doLogin = () => {
      const existingToken = wx.getStorageSync('token');
      if (existingToken) {
        this.reconnectSocket();
        return Promise.resolve(existingToken);
      }
      const openid = wx.getStorageSync('openid')
      const unionid = wx.getStorageSync('unionid')
      if (openid && unionid) {
        // openid已存在，直接登录
        loginByOpenid(openid, unionid)
      } else {
        wx.login({
          success: res => {
            if (res.code) {
              // 获取openid
              getOpenid(res.code)
            }
          }, fail: res => {
            console.log('wx.login调用报错')
            console.log(res)
            wx.showToast({
              title: '登录失败',
              icon: 'none'
            })
          }
        })
      }
      // 循环直到获取到token后调用socket连接
      return this.getTokenAsync().then(token => {
        console.log('获取到token', token);
        this.reconnectSocket();
        return token;
      });
    };
    this.loginPromise = doLogin().finally(() => {
      this.loginInProgress = false;
      this.loginPromise = null;
    });
    return this.loginPromise;
  },
  /**
   * 
   * @returns 循环获取到token为止
   */
  getTokenAsync(){
    return new Promise((resolve) => {
      const tryGet = () => {
        const token = wx.getStorageSync("token");
        if (token) {
          resolve(token);
        } else {
          console.log('尝试获取token, 获取不到token');
          setTimeout(tryGet, 1000);
        }
      };
      tryGet();
    });
  },
  /**
   * 
   * @param {*} title  标题
   * @param {*} content 内容
   * @param {*} msgType 消息类型， 默认是 warning 目前还有info， success
   * @param {*} canClick 是否可以点击
   * @param {string} [clickToPage='/pages/message-manage/message-manage'] 
   */
  showGlobalMessage(title, content, msgType = 'warning', canClick=true, clickToPage='/pages/message-manage/message-manage') {
    const pages = getCurrentPages();
    if (pages.length) {
      const page = pages[pages.length - 1];
      if (page.selectComponent) {
        const msg = page.selectComponent('#globalMessage');
        if (msg) {
          msg.showMessage(title, content, msgType, canClick, clickToPage);
        }
      }
    }
  },
  reconnectSocket() {
    const token = wx.getStorageSync('token');
    if (!token) return;
    if (this.socket) {
      try { this.socket.disconnect(); } catch (e) {}
      this.socket = null;
    }
    // 刚进来，设置重连错误次数为0, 让从0开始
    this.globalData.tryConnectErrorCount = 0;
    
    // 使用配置的socket地址
    const socketUrl = this.globalData.socketUrl;
    console.log('当前环境:', this.globalData.envName, 'Socket地址:', socketUrl);
    
    this.socket = io(socketUrl, {
      transports: ['websocket'],
      path: this.globalData.envName === '开发环境'? '/socket.io': '/socket-api/socket.io', // 明确指定 path
      query: {
        token: token,
        clientType: 'miniProgram'
      }
    });

    // 关键：监听连接错误
    this.socket.on('error', (err) => {
      console.error('socket error', err);
    });
    this.socket.on('connect_error', (err) => {
      this.globalData.tryConnectErrorCount ++;
      console.error('socket connect_error', err);
      console.info('失败重连次数tryConnectErrorCount : '+ this.globalData.tryConnectErrorCount);
      // 判断失败重连次数，达到60次，就跳转到登录页面
      if (this.globalData.tryConnectErrorCount > 520){
        wx.removeStorageSync('token')
        wx.showToast({ title: '请重新登录', icon: 'none' })
          setTimeout(() => {
            wx.redirectTo({ url: '/pages/login/login' })
          }, 500)
      }
      
    });

    this.socket.on('connect', (data) => {
      // 连接成功，设置重连错误次数为0
      this.globalData.tryConnectErrorCount = 0;
      console.log('socket connected 您已与服务器建立连接！');
      // this.socket.emit('message', { content: '你好', sender: 'user1', receiver: 'user2', eventType: "task" });
      this.showGlobalMessage('连接提醒', '您已与服务器建立连接！', 'success', false)
    });
    this.socket.on('disconnect', () => {
      // 自动断开连接，设置重连错误次数为0, 让从0开始
      this.globalData.tryConnectErrorCount = 0;
      console.log('socket disconnect');
      this.showGlobalMessage('连接提醒', '您已与服务器断开连接！点击跳转去重新登录。', 'warning', true, '/pages/login/login')
    });

    // 鉴权异常， 跳转到登录页面
    this.socket.on('auth_error', () => {
      // 自动断开连接，设置重连错误次数为0, 让从0开始
      this.globalData.tryConnectErrorCount = 0;
      console.log('socket auth_error');
      this.showGlobalMessage('连接提醒', '您已与服务器断开连接！点击跳转去重新登录。', 'warning', true, '/pages/login/login')
      setTimeout(() => {
        wx.redirectTo({ url: '/pages/login/login' })
      }, 400)
    });

    /**
     * 业务消息接听
     */
    this.socket.on('message', (msg) => {
      console.log('收到消息', msg);
      // 兼容字符串和对象
      if (typeof msg === 'string') {
        try {
          let data = JSON.parse(msg);
          this.showGlobalMessage(data.title, data.content, data.msgType, data.canClick, data.clickToPage);
        } catch (e) {
          console.warn('消息非JSON格式', msg);
        }
      } else if (typeof msg === 'object' && msg !== null) {
        // 直接处理对象格式的消息
        this.showGlobalMessage(msg.title, msg.content, msg.msgType, msg.canClick, msg.clickToPage);
      } else {
        console.warn('消息格式不支持', msg);
      }
    });
    
    
  },
  /**
   * 设置账户全局相关
   * @param {idx} idx 账户索引
   */
  setAccountIdxGlobal(idx) {
    this.globalData.globaAccountIndex = idx;
  },
  /**
   * 获取账户全局相关
   */ 
  async getAccountGlobal() {
    // 先读取本地缓存
    let accountList = wx.getStorageSync('accountBooks') || [];
    let accountListExpire = wx.getStorageSync('accountBooksExpire') || 0;
    const now = Date.now();
    
    // 检查缓存是否过期（1800秒 = 30分钟）
    const EXPIRE_TIME = 1800 * 1000; // 转换为毫秒
    if (!accountList || !accountList.length || (now - accountListExpire) > EXPIRE_TIME) {
      // 本地没有或已过期，调接口
      try {
        // 调用接口获取账户数据
        const res = await financeAccount.getAllAccounts();
        if (res && Array.isArray(res)) {
          accountList = res;
          // 放进缓存中，同时存储过期时间
          wx.setStorageSync('accountBooks', accountList);
          wx.setStorageSync('accountBooksExpire', now);
          // 赋值给全局
          this.globalData.globaAccountList = accountList;
          // 触发账户就绪回调
          if (this.accountReadyCallbacks && this.accountReadyCallbacks.length) {
            const cbs = this.accountReadyCallbacks.slice();
            this.accountReadyCallbacks = [];
            cbs.forEach(cb => { try { cb(); } catch (e) {} });
          }
        }
      } catch (e) {
        console.error("获取账户失败:", e)
        // wx.showToast({ title: '获取账户失败', icon: 'none' });
      }
    }
    if (!accountList || accountList.length < 1) {
      // wx.showToast({ title: '获取账户失败，请重新刷新或者重新进入小程序', icon: 'none' });
      // 实在找不到数据，返回空对象，免得报错
      return {
        accountList: [],
        accountIndex: -1
      }
    }
    let accountIndex = this.globalData.globaAccountIndex;
    if (accountIndex < 0) {
      // 没有加载才用默认的，加载过就用加载的
      accountIndex = Math.max(0, accountList.findIndex(item => item.defaultFlag === 'yes'));
      // 这是重新赋值，避免下次进来的时候，还是默认的
      this.globalData.globaAccountIndex = accountIndex;
    } else {
      // 加载过就用加载的
      const account = accountList[accountIndex];
      if (!account) {
        // 有index但是找不到，说明本地缓存数据异常，那就以最新的缓存数据中取其默认的数据
        accountIndex = Math.max(0, accountList.findIndex(item => item.defaultFlag === 'yes'));
        // 这是重新赋值，避免下次进来的时候，还是默认的
        this.globalData.globaAccountIndex = accountIndex;
      } else {
        // 有index且找到，说明本地缓存数据正常，那就用本地的
        accountIndex = accountList.findIndex(item => item.id === account.id);
      }
    }

    // 若此时账号数据已可用，也触发就绪回调（覆盖缓存命中场景）
    if (Array.isArray(accountList) && accountList.length && this.accountReadyCallbacks && this.accountReadyCallbacks.length) {
      const cbs = this.accountReadyCallbacks.slice();
      this.accountReadyCallbacks = [];
      cbs.forEach(cb => { try { cb(); } catch (e) {} });
    }

    return {
      accountList: accountList,
      accountIndex: accountIndex
    }
  },
  // 注册账户数据就绪回调
  onAccountReady(callback) {
    if (typeof callback !== 'function') return;
    const hasAccounts = Array.isArray(this.globalData.globaAccountList) && this.globalData.globaAccountList.length > 0;
    if (hasAccounts) {
      try { callback(); } catch (e) {}
    } else {
      this.accountReadyCallbacks.push(callback);
    }
  }
}) 